Skip to content

Fix/batch collect fees 259 - #266

Merged
Cybermaxi7 merged 2 commits into
MarketXpress:mainfrom
patrickNwafo:fix/batch-collect-fees-259
Aug 18, 2026
Merged

Fix/batch collect fees 259#266
Cybermaxi7 merged 2 commits into
MarketXpress:mainfrom
patrickNwafo:fix/batch-collect-fees-259

Conversation

@patrickNwafo

Copy link
Copy Markdown
Contributor

Summary

batch_collect_fees computed a fee per escrow, published BatchFeesCollectedEvent with the total, and returned that total — but never transferred a single token and never wrote any state. Every reported collection was fabricated, so any indexer/dashboard reading the event recorded revenue that didn't exist.

Changes

  • Real transfer, real bookkeeping. Each escrow's fee is already credited into PendingFee(collector, token) when it releases (the same pull-pattern ledger withdraw_fees drains). batch_collect_fees now decrements that ledger per collected escrow and performs one real token_client.transfer for the batch total — so it only ever moves funds the contract actually holds, never fabricates money.
  • Correct fee formula. Replaced the stale, duplicated inline calculation with calculate_fee_internal — the same whitelist- and native-asset-aware formula the single-escrow path uses.
  • No double-collection. Each collected escrow is flagged (EscrowFeeCollected) so its fee can never be paid out twice.
  • Batch size cap. New MAX_ESCROWS_PER_BATCH constant (50, mirroring MAX_ITEMS_PER_ESCROW) in types.rs; oversized batches are rejected with ContractError::TooManyItems.
  • Honest events. BatchFeesCollectedEvent fires only after a successful transfer, never on a zero-value call.
  • Non-existent escrow IDs still hard-error; wrong status, wrong token, or already-collected escrows are silently skipped rather than failing the whole batch.

Tests

  • Successful batch transfer across multiple escrows
  • Double-collection rejected (second call on the same IDs yields 0, no extra payout)
  • Over-limit batch rejected
  • Mixed eligible/ineligible escrows (released vs. still-funded)
  • Wrong-token escrows skipped

CI

patrickNwafo and others added 2 commits August 17, 2026 20:17
Closes MarketXpress#259

batch_collect_fees recomputed a fee per escrow, published
BatchFeesCollectedEvent with the total, and returned that total, but
never moved a single token and never wrote any state — every reported
collection was fabricated. Off-chain indexers trusting the event or
the return value recorded revenue that never existed.

Each escrow's fee is already credited into PendingFee(collector, token)
when it releases (the same pull-pattern ledger withdraw_fees drains).
batch_collect_fees now transfers that real, already-accrued balance to
the collector in one batch, itemized against the requested escrow_ids,
using the same calculate_fee_internal formula the single-escrow path
uses (whitelist- and native-asset-aware, unlike the stale duplicated
formula this replaces) — so it never fabricates money, only moves what
the contract actually holds.

- Decrements PendingFee(collector, token) by each collected escrow's
  fee and performs a single token transfer for the batch total.
- Flags each collected escrow (EscrowFeeCollected) so the same fee can
  never be paid out twice.
- Adds MAX_ESCROWS_PER_BATCH (50, mirroring MAX_ITEMS_PER_ESCROW) and
  rejects oversized batches with ContractError::TooManyItems.
- BatchFeesCollectedEvent now fires only after a successful transfer,
  never on a zero-value call.
- Non-existent escrow ids still hard-error; wrong status, wrong token,
  or already-collected escrows are silently skipped rather than
  failing the whole batch.

Tests: successful batch transfer, double-collection rejected,
over-limit rejected, mixed eligible/ineligible escrows, wrong-token
escrows skipped.

Verified: cargo fmt --check, cargo clippy --all-targets -- -D warnings,
cargo test (109 unit + 2 integration), and the wasm32v1-none release
build all pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Picks up upstream's escrow-payout-requires-funded fix (MarketXpress#255), mediation
window limit (MarketXpress#257), and upgrade timelock (MarketXpress#258). Only the shared
re-export list in lib.rs conflicted (additive on both sides); resolved
by keeping both sets of imports.
@Cybermaxi7

Copy link
Copy Markdown
Contributor

Wow, what a wonderful contribution
We at MarketXpress truly appreciate your contribution
We hope to see you contribute again
Thank you @patrickNwafo

@Cybermaxi7
Cybermaxi7 merged commit 21e53b0 into MarketXpress:main Aug 18, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[high] batch_collect_fees reports collected fees but transfers no funds

2 participants